//
// 类型用于创建类型别名
//
type Context = string | { context: string };
type Callback<T> = (text: T) => void;
const c: Context = "hello";
const c1: Context = { context: c };
const c2: Context = { context: "hi" };
const cb: Callback<Context> = (text: Context) => console.log(text);
console.log(typeof c, c);
console.log(typeof c1, c1);
console.log(typeof c2, c2);
console.log(typeof cb, cb("call"));
console.log(typeof cb, cb({ context: "call2" }));
// 错误，参数类型不匹配
//cb({ unexist: "sth" });
//db(100);

//
// 接口用于结构化数据，用作静态类型检查
//
interface Point {
  readonly x: number;
  readonly y: number;
}
// 只允许 z 轴变动
interface Point3D extends Point {
  z: number;
}
const point: Point = { x: 1, y: 2 };
const point3d: Point3D = { ...point, z: 3 };
console.log(typeof point, point);
console.log(typeof point3d, point3d);

//
// 类可以实现接口
//
class MyPoint implements Point3D {
  x = 1;
  y = 2;
  z = 3;
}
const myPoint: Point3D = new MyPoint();
// 错误， x 轴无法变动
//myPoint.x = 0;
myPoint.z = 10;
console.log(typeof myPoint, myPoint);

//
// 函数可以实现接口
//
interface SumFunc {
  (a: number, b: number): number;
}
const sum: SumFunc = function (a: number, b: number): number {
  return a + b;
};
console.log(typeof sum, sum, sum(1, 2));

export {};

//
// 带索引的类型可以实现接口
//
interface Strings {
  // 使用 number 作为索引会得到 string ，因为使用了 readonly 该数据类型不能使用索引赋值
  readonly [index: number]: string;
}
const strings: Strings = ["1", "2"];
// 错误，对象创建之后禁止使用索引修改元素
//strings[0] = "0";
console.log(typeof strings, strings);

//
// 类会隐式创建一个同名接口，所以可以使用类名指定变量类型，此处仅做说明无实用性
//
class Circle {
  center: Point = { x: 1, y: 2 };
  radius = 3;
}
// 使用 Circle 接口创建对象
const circle: Circle = { center: { x: 4, y: 5 }, radius: 6 };
// 使用 Circle 类创建对象
const circle2: Circle = new Circle();
console.log(typeof circle, circle);
console.log(typeof circle2, circle2);
